add BT instruction support to VMX MMIO decoder.
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Sat, 15 Oct 2005 06:43:08 +0000 (07:43 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Sat, 15 Oct 2005 06:43:08 +0000 (07:43 +0100)
Also extends TEST and OR instructions support for 16/32 bit operations,
these are needed for windows.

Signed-off-by: Xin Li <xin.b.li@intel.com>
Signed-off-by: Chengyuan Li <chengyuan.li@intel.com>
Signed-off-by: Nakajima Jun <nakajima.jun@intel.com>
xen/arch/x86/vmx_io.c
xen/arch/x86/vmx_platform.c
xen/include/asm-x86/vmx_platform.h

index 8809d2170425f470743ed328ed07061c71e2fc14..1d904e43a9bdc6c0d684c9fff49726023037f7aa 100644 (file)
@@ -624,6 +624,17 @@ static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
         set_eflags_SF(size, diff, regs);
         set_eflags_PF(size, diff, regs);
         break;
+
+    case INSTR_BT:
+        index = operand_index(src);
+        value = get_reg_value(size, index, 0, regs);
+
+        if (p->u.data & (1 << (value & ((1 << 5) - 1))))
+            regs->eflags |= X86_EFLAGS_CF;
+        else
+            regs->eflags &= ~X86_EFLAGS_CF;
+
+        break;
     }
 
     load_cpu_user_regs(regs);
index cd1a5b3b025e18e27369301bbe629f2817787d8c..87647ef1f7f39960156be399418fcf3463ee466b 100644 (file)
@@ -371,7 +371,7 @@ static int vmx_decode(unsigned char *opcode, struct instruction *instr)
     unsigned long eflags;
     int index, vm86 = 0;
     unsigned char rex = 0;
-    unsigned char tmp_size = 0;
+    unsigned char size_reg = 0;
 
     init_instruction(instr);
 
@@ -428,33 +428,47 @@ static int vmx_decode(unsigned char *opcode, struct instruction *instr)
 
     case 0x80:
     case 0x81:
-        if (((opcode[1] >> 3) & 7) == 7) { /* cmp $imm, m32/16 */
-            instr->instr = INSTR_CMP;
+        {
+            unsigned char ins_subtype = (opcode[1] >> 3) & 7;
 
-            if (opcode[0] == 0x80)
-                GET_OP_SIZE_FOR_BYTE(instr->op_size);
-            else
+            if (opcode[0] == 0x80) {
+                GET_OP_SIZE_FOR_BYTE(size_reg);
+                instr->op_size = BYTE;
+            } else {
                 GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+                size_reg = instr->op_size;
+            }
 
-            instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
-            instr->immediate = get_immediate(vm86, opcode+1, BYTE);
-            instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
+            instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
+            instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
+            instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
 
-            return DECODE_success;
-        } else
-            return DECODE_failure;
+            switch (ins_subtype) {
+                case 7: /* cmp $imm, m32/16 */
+                    instr->instr = INSTR_CMP;
+                    return DECODE_success;
+
+                case 1: /* or $imm, m32/16 */
+                    instr->instr = INSTR_OR;
+                    return DECODE_success;
+
+                default:
+                    printf("%x, This opcode isn't handled yet!\n", *opcode);
+                    return DECODE_failure;
+            }
+        }
 
     case 0x84:  /* test m8, r8 */
         instr->instr = INSTR_TEST;
         instr->op_size = BYTE;
-        GET_OP_SIZE_FOR_BYTE(tmp_size);
-        return mem_reg(tmp_size, opcode, instr, rex);
+        GET_OP_SIZE_FOR_BYTE(size_reg);
+        return mem_reg(size_reg, opcode, instr, rex);
 
     case 0x88: /* mov r8, m8 */
         instr->instr = INSTR_MOV;
         instr->op_size = BYTE;
-        GET_OP_SIZE_FOR_BYTE(tmp_size);
-        return reg_mem(tmp_size, opcode, instr, rex);
+        GET_OP_SIZE_FOR_BYTE(size_reg);
+        return reg_mem(size_reg, opcode, instr, rex);
 
     case 0x89: /* mov r32/16, m32/16 */
         instr->instr = INSTR_MOV;
@@ -464,8 +478,8 @@ static int vmx_decode(unsigned char *opcode, struct instruction *instr)
     case 0x8A: /* mov m8, r8 */
         instr->instr = INSTR_MOV;
         instr->op_size = BYTE;
-        GET_OP_SIZE_FOR_BYTE(tmp_size);
-        return mem_reg(tmp_size, opcode, instr, rex);
+        GET_OP_SIZE_FOR_BYTE(size_reg);
+        return mem_reg(size_reg, opcode, instr, rex);
 
     case 0x8B: /* mov m32/16, r32/16 */
         instr->instr = INSTR_MOV;
@@ -475,8 +489,8 @@ static int vmx_decode(unsigned char *opcode, struct instruction *instr)
     case 0xA0: /* mov <addr>, al */
         instr->instr = INSTR_MOV;
         instr->op_size = BYTE;
-        GET_OP_SIZE_FOR_BYTE(tmp_size);
-        return mem_acc(tmp_size, instr);
+        GET_OP_SIZE_FOR_BYTE(size_reg);
+        return mem_acc(size_reg, instr);
 
     case 0xA1: /* mov <addr>, ax/eax */
         instr->instr = INSTR_MOV;
@@ -486,8 +500,8 @@ static int vmx_decode(unsigned char *opcode, struct instruction *instr)
     case 0xA2: /* mov al, <addr> */
         instr->instr = INSTR_MOV;
         instr->op_size = BYTE;
-        GET_OP_SIZE_FOR_BYTE(tmp_size);
-        return acc_mem(tmp_size, instr);
+        GET_OP_SIZE_FOR_BYTE(size_reg);
+        return acc_mem(size_reg, instr);
 
     case 0xA3: /* mov ax/eax, <addr> */
         instr->instr = INSTR_MOV;
@@ -541,13 +555,21 @@ static int vmx_decode(unsigned char *opcode, struct instruction *instr)
             return DECODE_failure;
 
     case 0xF6:
-        if (((opcode[1] >> 3) & 7) == 0) { /* testb $imm8, m8 */
+    case 0xF7:
+        if (((opcode[1] >> 3) & 7) == 0) { /* test $imm8/16/32, m8/16/32 */
             instr->instr = INSTR_TEST;
-            instr->op_size = BYTE;
 
-            instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
+            if (opcode[0] == 0xF6) {
+                GET_OP_SIZE_FOR_BYTE(size_reg);
+                instr->op_size = BYTE;
+            } else {
+                GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+                size_reg = instr->op_size;
+            }
+
+            instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
             instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
-            instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
+            instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
 
             return DECODE_success;
         } else
@@ -583,6 +605,14 @@ static int vmx_decode(unsigned char *opcode, struct instruction *instr)
         instr->operand[0] = mk_operand(instr->op_size, 0, 0, MEMORY);
         return DECODE_success;
 
+    case 0xA3: /* bt r32, m32 */
+        instr->instr = INSTR_BT;
+        index = get_index(opcode + 1, rex);
+        instr->op_size = LONG;
+        instr->operand[0] = mk_operand(instr->op_size, index, 0, REGISTER);
+        instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
+        return DECODE_success;
+
     default:
         printf("0f %x, This opcode isn't handled yet\n", *opcode);
         return DECODE_failure;
@@ -843,9 +873,28 @@ void handle_mmio(unsigned long va, unsigned long gpa)
         mmio_opp->immediate = mmio_inst.immediate;
 
         /* send the request and wait for the value */
-        send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, mmio_inst.op_size, 0, IOREQ_READ, 0);
+        send_mmio_req(IOREQ_TYPE_COPY, gpa, 1,
+                      mmio_inst.op_size, 0, IOREQ_READ, 0);
         break;
 
+    case INSTR_BT:
+        {
+            unsigned long value = 0;
+            int index, size;
+
+            mmio_opp->instr = mmio_inst.instr;
+            mmio_opp->operand[0] = mmio_inst.operand[0]; /* bit offset */
+            mmio_opp->operand[1] = mmio_inst.operand[1]; /* bit base */
+
+            index = operand_index(mmio_inst.operand[0]);
+            size = operand_size(mmio_inst.operand[0]);
+            value = get_reg_value(size, index, 0, regs);
+
+            send_mmio_req(IOREQ_TYPE_COPY, gpa + (value >> 5), 1,
+                          mmio_inst.op_size, 0, IOREQ_READ, 0);
+            break;
+        }
+
     default:
         printf("Unhandled MMIO instruction\n");
         domain_crash_synchronous();
index a7a0e80641ea415d7dd80ff625feec003595549d..1dd3cf7c742f922bc181dae4c5b5c78df44e01c3 100644 (file)
@@ -27,8 +27,8 @@
 
 #define MAX_OPERAND_NUM 2
 
-#define mk_operand(size, index, seg, flag) \
-    (((size) << 24) | ((index) << 16) | ((seg) << 8) | (flag))
+#define mk_operand(size_reg, index, seg, flag) \
+    (((size_reg) << 24) | ((index) << 16) | ((seg) << 8) | (flag))
 
 #define operand_size(operand)   \
       ((operand >> 24) & 0xFF)
@@ -63,6 +63,7 @@
 #define INSTR_MOVZ 8
 #define INSTR_STOS 9
 #define INSTR_TEST 10
+#define INSTR_BT 11
 
 struct instruction {
     __s8    instr; /* instruction type */